package de.edb.dao;

import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import de.edb.model.Event;
import de.edb.model.Location;


public class LocationDao extends HibernateDaoSupport {
	private EventDao eventDao;
	
	public void setEventDao(EventDao eventDao) {
		this.eventDao = eventDao;
	}

	/**
	 * Creates a new {@link Location} and saves it in the DB.
	 * @param name
	 */
	public void create(String name) {
		Location l = new Location(name);
		save(l);
	}

	/**
	 * Returns a single location by its primary db key
	 * @param id the primary key of a {@link Location}
	 * @return a single Location
	 */
	public Location findById(int id) {
		HibernateTemplate template = getHibernateTemplate();
		return (Location) template.get(Location.class, id);
	}
	
	/**
	 * Returns all locations from the database.
	 * @return a list of Location
	 * @see Location
	 */
	public List<Location> findAll() {
		HibernateTemplate template = getHibernateTemplate();
		return template.loadAll(Location.class);
	}
	
	/**
	 * @return Location objects filtered by name from the database.
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<Location> findByName(final String keyword) {
		HibernateTemplate template = getHibernateTemplate();
		return (List<Location>) template.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(Location.class);
				criteria.add(Restrictions.ilike("name", keyword, MatchMode.ANYWHERE));
				List<Location> locations = criteria.list();
				return locations;
			}
		});
	}

	/**
	 * Saves the {@link Location} specified by the parameter in the database.
	 * @param location a {@link Location} object that should be saved in the db.
	 * @return the object specified by the parameter
	 */
	public Location save(Location location) {
		HibernateTemplate template = getHibernateTemplate();
		template.saveOrUpdate(location);
		return location;
	}



	/**
	 * Deletes the specified {@link Location} object from the database.
	 * @param location the {@link Location} to be deleted.
	 * @throws DaoException if the specified {@link Location} is included in a {@link Event}
	 */
	public void delete(Location location) throws DaoException {
		HibernateTemplate template = getHibernateTemplate();
		Set<Event> locationEvents = eventDao.findByLocation(location);
		if (locationEvents.size() == 0) {
			template.delete(location);
		} else {
			throw new DaoException("Location kann nicht gelöscht werden, da bereits Events angelegt sind.");
		}
	}

}